package com.zenithmind.document.service.impl;

import com.zenithmind.document.mapper.DocumentMapper;
import com.zenithmind.document.pojo.vo.DocumentVO;
import com.zenithmind.document.service.DocumentSearchService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 文档搜索服务实现类
 * 遵循单一职责原则：专注于文档搜索功能
 * 遵循依赖倒置原则：依赖抽象接口而不是具体实现
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DocumentSearchServiceImpl implements DocumentSearchService {

    private final DocumentMapper documentMapper;

    @Override
    public List<DocumentVO> searchDocuments(String keyword, String userId, Integer limit) {
        log.info("搜索文档: keyword={}, userId={}", keyword, userId);
        
        return documentMapper.searchDocuments(keyword, userId, limit);
    }

    @Override
    public List<DocumentVO> advancedSearchDocuments(String keyword, String categoryId,
                                                   String type, String userId, Integer limit) {
        log.info("高级搜索文档: keyword={}, categoryId={}, type={}, userId={}",
                keyword, categoryId, type, userId);

        try {
            // 构建高级搜索条件
            AdvancedSearchCriteria criteria = buildSearchCriteria(keyword, categoryId, type, userId, limit);

            // 执行搜索
            List<DocumentVO> results = executeAdvancedSearch(criteria);

            // 排序和过滤结果
            List<DocumentVO> filteredResults = filterAndSortResults(results, criteria);

            log.info("高级搜索完成: keyword={}, resultCount={}", keyword, filteredResults.size());

            return filteredResults;

        } catch (Exception e) {
            log.error("高级搜索失败: keyword={}, categoryId={}, type={}", keyword, categoryId, type, e);
            return new java.util.ArrayList<>();
        }
    }

    @Override
    public List<DocumentVO> searchDocumentsByTags(List<String> tags, String userId, Integer limit) {
        log.info("按标签搜索文档: tags={}, userId={}", tags, userId);

        if (tags == null || tags.isEmpty()) {
            return new java.util.ArrayList<>();
        }

        try {
            // 构建标签搜索条件
            TagSearchCriteria criteria = buildTagSearchCriteria(tags, userId, limit);

            // 执行标签搜索
            List<DocumentVO> results = executeTagSearch(criteria);

            // 按标签匹配度排序
            List<DocumentVO> sortedResults = sortByTagRelevance(results, tags);

            log.info("标签搜索完成: tags={}, resultCount={}", tags, sortedResults.size());

            return sortedResults;

        } catch (Exception e) {
            log.error("标签搜索失败: tags={}, userId={}", tags, userId, e);
            return new java.util.ArrayList<>();
        }
    }

    @Override
    public List<DocumentVO> getRelatedDocuments(String documentId, String userId, Integer limit) {
        log.info("获取相关文档: documentId={}, userId={}", documentId, userId);
        
        return documentMapper.selectRelatedDocuments(documentId, userId, limit);
    }

    @Override
    public List<DocumentVO> getRecommendedDocuments(String userId, Integer limit) {
        log.info("获取推荐文档: userId={}", userId);
        
        return documentMapper.selectRecommendedDocuments(userId, limit);
    }

    @Override
    public List<DocumentVO> getHotDocuments(Integer limit) {
        log.info("获取热门文档");
        
        // TODO: 修复方法参数不匹配问题
        return new java.util.ArrayList<>();
    }

    @Override
    public List<DocumentVO> getLatestDocuments(String userId, Integer limit) {
        log.info("获取最新文档: userId={}", userId);
        
        return documentMapper.selectLatestDocuments(userId, limit);
    }

    @Override
    public List<DocumentVO> getFavoriteDocuments(String userId, Integer limit) {
        log.info("获取收藏文档: userId={}", userId);
        
        return documentMapper.selectFavoriteDocuments(userId, limit);
    }

    @Override
    public List<DocumentVO> getRecentDocuments(String userId, Integer limit) {
        log.info("获取最近访问文档: userId={}", userId);
        
        return documentMapper.selectRecentDocuments(userId, limit);
    }

    @Override
    public List<DocumentVO> getUserDocuments(String creatorId, Integer limit) {
        log.info("获取用户文档: creatorId={}", creatorId);
        
        return documentMapper.selectUserDocuments(creatorId, limit);
    }

    @Override
    public List<DocumentVO> getDocumentsByCategory(String categoryId, String userId, Integer limit) {
        log.info("按分类获取文档: categoryId={}, userId={}", categoryId, userId);
        
        return documentMapper.selectCategoryDocuments(categoryId, userId, limit);
    }

    /**
     * 高级搜索条件类
     */
    private static class AdvancedSearchCriteria {
        private String keyword;
        private String categoryId;
        private String type;
        private String userId;
        private Integer limit;
        private java.time.LocalDateTime startDate;
        private java.time.LocalDateTime endDate;
        private Long minSize;
        private Long maxSize;

        // Getters and Setters
        public String getKeyword() { return keyword; }
        public void setKeyword(String keyword) { this.keyword = keyword; }

        public String getCategoryId() { return categoryId; }
        public void setCategoryId(String categoryId) { this.categoryId = categoryId; }

        public String getType() { return type; }
        public void setType(String type) { this.type = type; }

        public String getUserId() { return userId; }
        public void setUserId(String userId) { this.userId = userId; }

        public Integer getLimit() { return limit; }
        public void setLimit(Integer limit) { this.limit = limit; }

        public java.time.LocalDateTime getStartDate() { return startDate; }
        public void setStartDate(java.time.LocalDateTime startDate) { this.startDate = startDate; }

        public java.time.LocalDateTime getEndDate() { return endDate; }
        public void setEndDate(java.time.LocalDateTime endDate) { this.endDate = endDate; }

        public Long getMinSize() { return minSize; }
        public void setMinSize(Long minSize) { this.minSize = minSize; }

        public Long getMaxSize() { return maxSize; }
        public void setMaxSize(Long maxSize) { this.maxSize = maxSize; }
    }

    /**
     * 标签搜索条件类
     */
    private static class TagSearchCriteria {
        private java.util.List<String> tags;
        private String userId;
        private Integer limit;
        private String matchMode; // "all" 或 "any"

        public java.util.List<String> getTags() { return tags; }
        public void setTags(java.util.List<String> tags) { this.tags = tags; }

        public String getUserId() { return userId; }
        public void setUserId(String userId) { this.userId = userId; }

        public Integer getLimit() { return limit; }
        public void setLimit(Integer limit) { this.limit = limit; }

        public String getMatchMode() { return matchMode; }
        public void setMatchMode(String matchMode) { this.matchMode = matchMode; }
    }

    /**
     * 构建搜索条件
     */
    private AdvancedSearchCriteria buildSearchCriteria(String keyword, String categoryId,
                                                      String type, String userId, Integer limit) {
        AdvancedSearchCriteria criteria = new AdvancedSearchCriteria();
        criteria.setKeyword(keyword);
        criteria.setCategoryId(categoryId);
        criteria.setType(type);
        criteria.setUserId(userId);
        criteria.setLimit(limit != null ? limit : 20);

        // 设置默认的搜索范围
        criteria.setStartDate(java.time.LocalDateTime.now().minusYears(1)); // 最近一年
        criteria.setMaxSize(100L * 1024 * 1024); // 最大100MB

        return criteria;
    }

    /**
     * 执行高级搜索
     */
    private java.util.List<DocumentVO> executeAdvancedSearch(AdvancedSearchCriteria criteria) {
        // TODO: 实现真实的高级搜索逻辑
        // 这里应该调用数据库进行复杂查询

        java.util.List<DocumentVO> results = new java.util.ArrayList<>();

        // 模拟搜索结果
        if (criteria.getKeyword() != null && !criteria.getKeyword().trim().isEmpty()) {
            // 基础关键词搜索
            results = documentMapper.searchDocuments(criteria.getKeyword(), criteria.getUserId(), criteria.getLimit());
        } else {
            // 无关键词时按条件筛选
            results = documentMapper.selectCategoryDocuments(criteria.getCategoryId(), criteria.getUserId(), criteria.getLimit());
        }

        return results;
    }

    /**
     * 过滤和排序结果
     */
    private java.util.List<DocumentVO> filterAndSortResults(java.util.List<DocumentVO> results,
                                                           AdvancedSearchCriteria criteria) {
        return results.stream()
                .filter(doc -> filterByType(doc, criteria.getType()))
                .filter(doc -> filterBySize(doc, criteria.getMinSize(), criteria.getMaxSize()))
                .filter(doc -> filterByDate(doc, criteria.getStartDate(), criteria.getEndDate()))
                .sorted((a, b) -> compareByRelevance(a, b, criteria.getKeyword()))
                .limit(criteria.getLimit())
                .collect(java.util.stream.Collectors.toList());
    }

    /**
     * 按类型过滤
     */
    private boolean filterByType(DocumentVO doc, String type) {
        return type == null || type.isEmpty() || type.equals(doc.getType());
    }

    /**
     * 按大小过滤
     */
    private boolean filterBySize(DocumentVO doc, Long minSize, Long maxSize) {
        if (doc.getFileSize() == null) return true;
        if (minSize != null && doc.getFileSize() < minSize) return false;
        if (maxSize != null && doc.getFileSize() > maxSize) return false;
        return true;
    }

    /**
     * 按日期过滤
     */
    private boolean filterByDate(DocumentVO doc, java.time.LocalDateTime startDate, java.time.LocalDateTime endDate) {
        if (doc.getCreateTime() == null) return true;
        if (startDate != null && doc.getCreateTime().isBefore(startDate)) return false;
        if (endDate != null && doc.getCreateTime().isAfter(endDate)) return false;
        return true;
    }

    /**
     * 按相关性比较
     */
    private int compareByRelevance(DocumentVO a, DocumentVO b, String keyword) {
        if (keyword == null || keyword.isEmpty()) {
            // 无关键词时按创建时间倒序
            return b.getCreateTime().compareTo(a.getCreateTime());
        }

        // 计算相关性得分
        int scoreA = calculateRelevanceScore(a, keyword);
        int scoreB = calculateRelevanceScore(b, keyword);

        return Integer.compare(scoreB, scoreA); // 高分在前
    }

    /**
     * 计算相关性得分
     */
    private int calculateRelevanceScore(DocumentVO doc, String keyword) {
        int score = 0;
        String lowerKeyword = keyword.toLowerCase();

        // 标题匹配得分更高
        if (doc.getTitle() != null && doc.getTitle().toLowerCase().contains(lowerKeyword)) {
            score += 10;
        }

        // 描述匹配
        if (doc.getDescription() != null && doc.getDescription().toLowerCase().contains(lowerKeyword)) {
            score += 5;
        }

        // 内容匹配（如果VO中有content字段）
        // if (doc.getContent() != null && doc.getContent().toLowerCase().contains(lowerKeyword)) {
        //     score += 3;
        // }

        return score;
    }

    /**
     * 构建标签搜索条件
     */
    private TagSearchCriteria buildTagSearchCriteria(java.util.List<String> tags, String userId, Integer limit) {
        TagSearchCriteria criteria = new TagSearchCriteria();
        criteria.setTags(tags);
        criteria.setUserId(userId);
        criteria.setLimit(limit != null ? limit : 20);
        criteria.setMatchMode("any"); // 默认匹配任意标签

        return criteria;
    }

    /**
     * 执行标签搜索
     */
    private java.util.List<DocumentVO> executeTagSearch(TagSearchCriteria criteria) {
        // TODO: 实现真实的标签搜索逻辑
        // 这里应该调用数据库进行标签查询

        List<DocumentVO> results = new java.util.ArrayList<>();

        // 模拟标签搜索
        for (String tag : criteria.getTags()) {
            java.util.List<DocumentVO> tagResults = searchDocumentsByTag(tag, criteria.getUserId(), criteria.getLimit());
            results.addAll(tagResults);
        }

        // 去重
        return results.stream()
                .distinct()
                .collect(java.util.stream.Collectors.toList());
    }

    /**
     * 按单个标签搜索
     */
    private java.util.List<DocumentVO> searchDocumentsByTag(String tag, String userId, Integer limit) {
        // TODO: 实现单个标签搜索
        // 这里应该调用数据库查询包含指定标签的文档

        // 模拟搜索结果
        java.util.List<DocumentVO> results = new java.util.ArrayList<>();

        // 可以调用现有的搜索方法作为临时实现
        return documentMapper.searchDocuments(tag, userId, limit);
    }

    /**
     * 按标签相关性排序
     */
    private java.util.List<DocumentVO> sortByTagRelevance(java.util.List<DocumentVO> results, java.util.List<String> tags) {
        return results.stream()
                .sorted((a, b) -> {
                    int scoreA = calculateTagRelevanceScore(a, tags);
                    int scoreB = calculateTagRelevanceScore(b, tags);
                    return Integer.compare(scoreB, scoreA); // 高分在前
                })
                .collect(java.util.stream.Collectors.toList());
    }

    /**
     * 计算标签相关性得分
     */
    private int calculateTagRelevanceScore(DocumentVO doc, java.util.List<String> searchTags) {
        int score = 0;

        // 获取文档的标签
        java.util.List<String> docTags = getDocumentTags(doc);

        // 计算匹配的标签数量
        for (String searchTag : searchTags) {
            for (String docTag : docTags) {
                if (docTag.toLowerCase().contains(searchTag.toLowerCase())) {
                    score += 10; // 完全匹配
                } else if (searchTag.toLowerCase().contains(docTag.toLowerCase())) {
                    score += 5; // 部分匹配
                }
            }
        }

        return score;
    }

    /**
     * 获取文档标签
     */
    private java.util.List<String> getDocumentTags(DocumentVO doc) {
        // TODO: 实现获取文档标签的逻辑
        // 这里应该从数据库或文档对象中获取标签

        java.util.List<String> tags = new java.util.ArrayList<>();

        // 模拟从文档标题和描述中提取标签
        if (doc.getTitle() != null) {
            String[] titleWords = doc.getTitle().split("\\s+");
            for (String word : titleWords) {
                if (word.length() > 2) {
                    tags.add(word);
                }
            }
        }

        return tags;
    }
}
